package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.domain.entity.ext.CkPaasFormDataEntityExt;
import com.xbongbong.paas.enums.AggTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.bi.commons.pojo.AggFieldPojo;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.service.toolbox.statistic.util.ChartResultUtil;
import com.xbongbong.pro.statistic.enums.NumFormatEnum;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.AggsBucketsPojo;
import com.xbongbong.pro.statistics.service.CkPaasFormDataService;
import com.xbongbong.pro.statistics.service.StatisticBiFormDataService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 查询表的汇总
 *
 * @ClassName QueryTableSumHelper
 * @Author 梁鲁江
 * 创建时间 2021/12/30 11:25
 * 修改时间  2021/12/30 11:25
 **/
@Component
public class QueryTableSumHelper {
    @Resource
    private CommonHelper commonHelper;
    @Resource
    private AggregationlHelper aggregationlHelper;
    @Resource
    private StatisticBiFormDataService statisticBiFormDataService;
    @Resource
    private CkPaasFormDataService ckPaasFormDataService;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private ComputedHelp computedHelp;
    
    public List<AggsBucketsPojo>  queryTableSum(ChartEntity chartEntity, String sql, boolean isSingle) throws XbbException {
        boolean subSqlFlag = false;
        List<AggsBucketsPojo> aggList = new ArrayList<>();
        //第一页的时候才运算
        JSONArray summaryAttr = chartEntity.getSummaryAttr();
        if (summaryAttr != null && summaryAttr.size() > 0) {
            JSONArray displayAttr = chartEntity.getDisplayAttr();
            displayAttr.addAll(summaryAttr);
            List<ChartFieldAttrPojo> fieldAttrPojoList = JSONArray.parseArray(displayAttr.toJSONString(), ChartFieldAttrPojo.class);
            for (ChartFieldAttrPojo chartFieldAttrPojo : fieldAttrPojoList) {
                if (!Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(), chartFieldAttrPojo.getFieldType())) {
                    continue;
                }
                //计算字段中包含count、countd公式时，sql的格式会变更为子查询sql的格式
                Boolean countFlag = chartFieldAttrPojo.getFormulaInfo().getBoolean("countFlag");
                if (Objects.nonNull(countFlag) && countFlag){
                    subSqlFlag = true;
                    break;
                }
            }
            Map<String,String> realKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, AggFieldPojo> aggFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> aggFieldsList = new ArrayList<>();
            List<String> sumTotalFieldsList = new ArrayList<>();
            List<String> summaryColumnAlisa = new ArrayList<>();
            List<String> subQuerySqlOfCountList = new ArrayList<>();
            Map<Long, String> formIdTableMap = commonHelper.getFormIdTableMap(chartEntity, isSingle);
            Map<String, String> sortMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<ChartFieldAttrPojo> list = JSONArray.parseArray(summaryAttr.toJSONString(), ChartFieldAttrPojo.class);
            for (ChartFieldAttrPojo fieldAttrPojo : list) {
                AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(fieldAttrPojo.getAggType());
                if(Objects.equals(fieldAttrPojo.getAttr(),PaasConstant.COUNT)){
                    aggTypeEnum =  AggTypeEnum.COUNT;
                }
                String attr = fieldAttrPojo.getAttr();
                if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(), fieldAttrPojo.getFieldType())) {
                    computedHelp.addComputedField(chartEntity,fieldAttrPojo,aggTypeEnum,PaasConstant.LEFT,null,formIdTableMap,aggFieldMap,aggFieldsList,sortMap,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
                } else {
                    Long formId = fieldAttrPojo.getFormId();
                    aggregationlHelper.addValuesField(PaasConstant.LEFT,formIdTableMap, aggFieldMap, aggFieldsList, isSingle, fieldAttrPojo, aggTypeEnum, formId, attr,sortMap, sumTotalFieldsList,summaryColumnAlisa);
                    if(subSqlFlag){
                        String pojoAttr = fieldAttrPojo.getAttr();
                        realKeyMap.put(summaryColumnAlisa.get(summaryColumnAlisa.size() - 1),pojoAttr);
                        summaryColumnAlisa.set(summaryColumnAlisa.size() - 1,pojoAttr);
                    }
                }
            }
            //汇总字段select部分
            List<String> selectFiledList;
            //切割的关键字：子查询FROM，普通from
            String splitSqlRegex;
            if (subSqlFlag){
                summaryColumnAlisa.addAll(subQuerySqlOfCountList);
                selectFiledList = summaryColumnAlisa;
                splitSqlRegex = XbbConstant.FROM;
            }else{
                selectFiledList = aggFieldsList;
                splitSqlRegex = "from";
            }
            String selectFiledSql = computedHelp.dealDataQueryAggFieldSql(selectFiledList);
            String[] array = sql.split(splitSqlRegex, 2);
            String oldSql = array[1];
            if(oldSql.contains("ORDER BY")){
                oldSql = oldSql.substring(0,oldSql.lastIndexOf("ORDER BY"));
            }
            if(subSqlFlag){
                oldSql += XbbConstant.R_P;
            }
            sql = "select " + selectFiledSql + " from " + oldSql;
            List<CkPaasFormDataEntityExt> ckSingleResultList = null;
            List ckMultiResultList = null;
            JSONArray resultArr;
            if (isSingle) {
                ckSingleResultList = ckPaasFormDataService.findEntitysBySql(sql);
                resultArr = JSONArray.parseArray(JSON.toJSONString(ckSingleResultList));
            } else {
                ckMultiResultList = statisticBiFormDataService.findEntitys(sql);
                resultArr = JSONArray.parseArray(JSON.toJSONString(ckMultiResultList));
            }
            if(CollectionUtils.isNotEmpty(resultArr)){
                Map<String,ChartFieldAttrPojo> map = new HashMap<>(list.size());
                for (ChartFieldAttrPojo fieldAttrPojo : list) {
                    String attr = fieldAttrPojo.getAttr();
                    map.put(attr,fieldAttrPojo);
                }
                for (int i = 0; i < resultArr.size(); i++) {
                    JSONObject resultObj = resultArr.getJSONObject(i);
                    if (resultObj == null) {
                        continue;
                    }
                    for (String key : aggFieldMap.keySet()) {
                        String tmpKey = key;
                        if (realKeyMap.containsKey(tmpKey)){
                            tmpKey = realKeyMap.get(tmpKey);
                        }
                        String value = resultObj.getString(tmpKey);
                        if(StringUtil.isNotEmpty(value)){
                            ChartFieldAttrPojo fieldAttrPojo = map.get(aggFieldMap.get(key).getAttr());
                            int accuracy = fieldAttrPojo.getAccuracy() == null ? 0 : fieldAttrPojo.getAccuracy();
                            Integer percentUsed = fieldAttrPojo.getPercentUsed();
                            Integer groupingUsed = fieldAttrPojo.getGroupingUsed() == null ? fieldAttrPojo.getAmountFlag() : fieldAttrPojo.getGroupingUsed();
                            // 百分比要先扩两位小数，后面再减
                            if (Objects.equals(percentUsed, 1)) {
                                accuracy += 2;
                            }
                            Integer numFormat = fieldAttrPojo.getNumFormat();
                            NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(numFormat);
                            String unit = numFormatEnum.getNoYuanUnit();
                            String newVal = String.valueOf(ChartResultUtil.formatVal4Num(new BigDecimal(value), numFormatEnum));
                            if (Objects.equals(percentUsed, 1)) {
                                accuracy -= 2;
                            }
                            String formatVal = attrDecimalPrecisionHelper.getNumberFormat(newVal, accuracy, groupingUsed, percentUsed);
                            if (StringUtil.isNotEmpty(unit)) {
                                formatVal += unit;
                            }
                            AggsBucketsPojo aggsBucketsPojo = new AggsBucketsPojo();
                            aggsBucketsPojo.setKey(fieldAttrPojo.getAttr() + "&" + fieldAttrPojo.getFieldType());
                            aggsBucketsPojo.setValue(formatVal);
                            aggList.add(aggsBucketsPojo);
                        }
                    }

                }
            }
        }
        return aggList;
    }

}
